
package com.goldsand.collaboration.handoff.server.connection;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.util.Log;

import com.goldsand.collaboration.handoff.common.connection.BroadcastReceiveThread;
import com.goldsand.collaboration.handoff.common.connection.BroadcastSenderTask;
import com.goldsand.collaboration.handoff.common.connection.NewMessageListener;
import com.goldsand.collaboration.handoff.common.connection.Utils;

import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;

public class SocketServerService extends Service implements NewMessageListener {
    private static final String TAG = "SocketServerService";
    private static final int SERVER_PORT = 10081;
    private static final int CLIENT_BROADCAST_THREAD_PORT = 10082;
    private static final int SERVER_PROADCAST_THREAD_PORT = 10083;

    private static final String ACTION_SERVER_IN = "com.goldsand.collaboration.handoff.server_IN";
    private static final String ACTION_EXIT_SERVER = "com.goldsand.collaboration.handoff.service_OUT";

    private static final int HANDLER_MESSAGE_STOP_SERVICE = 1;
    private static final int HANDLER_MESSAGE_UPDATE_NOTIFICATION = 2;
    private static final int STOP_SERVICE_DELY = 10 * 1000; // Dely 10s to stop service.

    private BroadcastReceiveThread mClientBroadCastReceiverThread = null;
    private SocketServerConnectionThread mSocketServerThread = null;
    private List<NewMessageListener> mSocketServerMessageListeners = new ArrayList<NewMessageListener>();
    private NotificationManager mNotificationManager;
    private static final int NOTIFICATION_ID = 1;

    public static Intent createServerInIntent() {
        Intent intent = new Intent();
        intent.setAction(ACTION_SERVER_IN);
        return intent;
    }

    public static Intent createServerOutIntent() {
        Intent intent = new Intent();
        intent.setAction(ACTION_EXIT_SERVER);
        return intent;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mClientBroadCastReceiverThread = new BroadcastReceiveThread(CLIENT_BROADCAST_THREAD_PORT);
        mClientBroadCastReceiverThread.setMessageListener(this);
        mSocketServerThread = new SocketServerConnectionThread("socket_connection_thread");
        mSocketServerThread.setNewMessageReceiveListener(this);
        Notification notification = new Notification();
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        startForeground(NOTIFICATION_ID, notification);
    }

    public void addSocketServerMessageListener(NewMessageListener listener) {
        synchronized (mSocketServerMessageListeners) {
            mSocketServerMessageListeners.add(listener);
        }
    }

    public void removeSocketServerMessageListener(NewMessageListener listener) {
        synchronized (mSocketServerMessageListeners) {
            mSocketServerMessageListeners.remove(listener);
        }
    }

    private void publishNewMessage(String message) {
        synchronized (mSocketServerMessageListeners) {
            for (NewMessageListener listener : mSocketServerMessageListeners) {
                listener.onNewMessageReceived(null, message);
            }
        }
    }

    public void sendDataToClient(String data) {
        Log.v(TAG, "send message to target data = " + data + " mSocketServerThread.isConnected()="
                + mSocketServerThread.isConnected());
        if (mSocketServerThread.isConnected()) {
            try {
                mSocketServerThread.sendDataToClient(data);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onNewMessageReceived(String threadName, String message) {
        
        if (TextUtils.equals(threadName, mClientBroadCastReceiverThread.getName())) {
            String currentIp = null;
            try {
                currentIp = Utils.getLocalHostIp();
            } catch (SocketException e) {
                e.printStackTrace();
            }
            new BroadcastSenderTask(null).execute(SERVER_PROADCAST_THREAD_PORT + "", currentIp
                    + ":" + SERVER_PORT);
        } else if (TextUtils.equals(threadName, mSocketServerThread.getName())) {
            
        }
        publishNewMessage(message);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent == null)
            return super.onStartCommand(intent, flags, startId);
        String action = intent.getAction();
        Log.d(TAG, "on start command action = " + action);
        // Connected to wifi, start server listener.
        if (ACTION_SERVER_IN.equals(action)) {
            // Setup1. Start socket server thread. wait for connection.
            Log.d(TAG, " ServerIn socketServerThread isAlive = " + mSocketServerThread.isAlive()
                    + " connected=" + mSocketServerThread.isConnected());
            if (!mSocketServerThread.isAlive() && !mSocketServerThread.isConnected()) {
                mSocketServerThread.start();
            }

            Log.d(TAG, " ServerIn mClientBroadCastReceiverThread isAlive = " + mClientBroadCastReceiverThread.isAlive()
                    + " connected=" + mClientBroadCastReceiverThread.isThreadRuning());
            // Setup2. Start listening to client broadcast.
            if (!mClientBroadCastReceiverThread.isAlive()) {
                mClientBroadCastReceiverThread.start();
            }

            // Setup3. Send broadcast to client, tell the client the server's ip
            // and port.
            String currentIp = null;
            try {
                currentIp = Utils.getLocalHostIp();
            } catch (SocketException e) {
                e.printStackTrace();
            }
            new BroadcastSenderTask(null).execute(SERVER_PROADCAST_THREAD_PORT + "", currentIp
                    + ":" + SERVER_PORT);
            // Exit the service,but disconnected the socket first.
        } else if (ACTION_EXIT_SERVER.equals(action)) {
            mClientBroadCastReceiverThread.stopReceive();
            mSocketServerThread.stopRuning();

            mHandler.sendEmptyMessageDelayed(HANDLER_MESSAGE_STOP_SERVICE, STOP_SERVICE_DELY);
        } else {
            Log.e(TAG, "can hold the action" + action);
        }
        return super.onStartCommand(intent, flags, startId);
    }

    Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            int what = msg.what;
            switch (what) {
                case HANDLER_MESSAGE_STOP_SERVICE:
                    stopSelf();
                    break;
                case HANDLER_MESSAGE_UPDATE_NOTIFICATION:
                    NotificationCompat.Builder builder = new NotificationCompat.Builder(
                            SocketServerService.this).setContentText((CharSequence) msg.obj);
                    mNotificationManager.notify(NOTIFICATION_ID, builder.build());
                    break;
                default:
                    break;
            }
        };
    };

//TODO notification
//    private void upDataNotification(String message) {
//        Message msg = mHandler.obtainMessage(HANDLER_MESSAGE_UPDATE_NOTIFICATION);
//        msg.obj = message;
//        msg.sendToTarget();
//    }

    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    public class MyBinder extends Binder {
        public SocketServerService getService() {
            return SocketServerService.this;
        }
    }

}
